/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 *
 */

import path from 'path';

import { HvigorCoreNode } from '@ohos/hvigor';
import { DependencyInfoType } from '@ohos/hvigor-arkts-compose';

import { BuildArtifactExtension } from '../../const/build-directory-const.js';
import { ProjectModel } from '../../model/project/project-model.js';
import { DependRemoteHspInfo, OhpmDependencyInfo } from '../../plugin/context/plugin-context.js';
import { Dependency, DependencyEnum, DependencyType } from '../../project/dependency/core/dependency-interface.js';
import { DependencyManager, ModulePkgNode, DependencyCollector, DependencyFilter } from '../../project/dependency/dependency-manager.js';
import { ModuleDependencyInfo } from '../../project/dependency/module-dependency-info.js';
import { toUnixPath } from '../../utils/copy-resources-util.js';
import { OhosLogger } from '../../utils/log/ohos-logger.js';
import { getRemoteHspPathMap } from '../../utils/remote-hsp-utils.js';
import { ModuleTaskService } from './module-task-service.js';
import { ProjectTaskService } from './project-task-service.js';
import { findTargetProduct } from '../../common/find-target-product.js';
import { ArkTSVersionConst } from '../../const/common-const.js';

enum DependencyCacheKey {
  AllHspDependencies,
  RootByteCodeHarDependencies,
  RootOtherDependencies,
  RootHspDependencies,
  AffectsCompilationDependencies,
  AllByteCodeHarDependencies
}

interface DependencyCacheValue {
  dependencies: Dependency[];
  moduleDepMap: Map<string, Dependency>;
}

/**
 * @description 依赖收集缓存装饰器，避免多次遍历依赖树
 * @param cacheKey
 * @constructor
 */
function Cacheable(cacheKey: DependencyCacheKey) {
  return function (target: TaskService, methodName: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    if (typeof originalMethod !== 'function') {
      return;
    }
    descriptor.value = function (...args: any[]) {
      const dependencyCache = (this as TaskService).getDependencyCache();
      if (dependencyCache.has(cacheKey)) {
        return dependencyCache.get(cacheKey);
      }
      const value = originalMethod.apply(this, args);
      dependencyCache.set(cacheKey, value);
      return value;
    };
  };
}

/**
 * 任务流服务的基础类
 *
 * @since 2022/1/20
 */
export class TaskService {
  protected hvigorNode: HvigorCoreNode;
  protected readonly _projectModel: ProjectModel;
  private _moduleDependencyInfo: ModuleDependencyInfo | undefined;
  protected _dependencyManager: DependencyManager;
  protected _isFaMode: boolean;
  private log: OhosLogger = OhosLogger.getLogger('TaskService');
  // 各种形式的依赖收集缓存
  private _dependencyCache: Map<DependencyCacheKey, DependencyCacheValue | Dependency[]> = new Map();

  constructor(node: HvigorCoreNode, projectModel: ProjectModel, dependencyManager: DependencyManager, isFaMode: boolean) {
    this.hvigorNode = node;
    this._projectModel = projectModel;
    this._dependencyManager = dependencyManager;
    this._isFaMode = isFaMode;
  }

  getDependencyCache() {
    return this._dependencyCache;
  }

  // 特定的生命周期上执行此函数完成依赖收集
  initDependencyInfo() {
    this.log.debug('Start to initialize dependency information.');
    this._moduleDependencyInfo = this._dependencyManager.createModelDependencyInfo();
  }

  isFaMode(): boolean {
    return this._isFaMode;
  }

  getNode() {
    return this.hvigorNode;
  }

  getProjectModel(): ProjectModel {
    return this._projectModel;
  }

  /**
   * 获取所有依赖的main对应文件的路径的集合
   * @returns {string[]}
   */
  getDependencyMainPaths(): string[] {
    return this.getDependencyInfo()
      .getNpmDependencies()
      .map((value) => {
        return value.getDependencyMainFilePath();
      });
  }

  /**
   * 获取所有依赖在node_modules中路径的集合
   * @returns {string[]}
   */
  getDependencyRootPaths(): string[] {
    return this.getDependencyInfo()
      .getNpmDependencies()
      .map((value) => {
        return value.getDependencyRootPath();
      });
  }

  /**
   * 获取不排除Hsp的间接依赖和DevDependencies的所有依赖
   */
  getAllModuleOrProjectDependencies(): Dependency[] {
    return this._dependencyManager.collectModelOrProjectAllDependencyInfo()
  }

  /**
   * 获取不排除Hsp的间接依赖和DevDependencies的所有三方依赖
   */
  getAllOtherDependencies(): Dependency[] {
    return this._dependencyManager.collectModelOrProjectAllDependencyInfo().filter((dependency) => !dependency.isLocal());
  }

  // 收集依赖中的路径信息的map用于增量判断
  getDependencyName2RootPath(): any {
    const map = new Map<string, string>();
    for (const dep of this._dependencyManager.collectAllDependenciesForPkgInfo().npmDependencies) {
      const name = dep.getDependencyName();
      if (map.has(name)) {
        return false;
      }
      map.set(name, dep.getDependencyRootPath());
    }
    return map;
  }

  // 收集依赖中的部分信息（版本号）的map用于增量判断
  getDependencyName2DepInfo(): Map<string, DependencyInfoType> {
    const map = new Map<string, DependencyInfoType>();
    const selfDependency = this.getDependencyInfo().getSelfAsDependency();
    // 当自身为har时，将自身的信息记录进去，因为构建字节码har时，ohmurl中含有自身的版本号
    if (selfDependency.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HAR) {
      map.set(selfDependency.getDependencyName(), {
        dependencyType: selfDependency.getDependencyType(),
        isByteCodeHar: selfDependency.isByteCodeHarDependency(),
        pkgRootPath: selfDependency.getDependencyRootPath(),
        pkgName: selfDependency.getPackageName(),
        pkgVersion: selfDependency.getDependencyVersion()
      });
    }
    for (const dep of this._dependencyManager.collectAllDependenciesForPkgInfo().npmDependencies) {
      const name = dep.getDependencyName();
      if (map.has(name)) {
        return new Map<string, DependencyInfoType>();
      }
      map.set(name, {
        dependencyType: dep.getDependencyType(),
        isByteCodeHar: dep.isByteCodeHarDependency(),
        pkgRootPath: dep.getDependencyRootPath(),
        pkgName: dep.getPackageName(),
        pkgVersion: dep.getDependencyVersion()
      });
    }
    return map;
  }

  /**
   * 获取所有har依赖
   * @returns {Dependency[]}
   */
  getHarDependencies(): Dependency[] {
    return this.getDependencyInfo()
      .getNpmDependencies()
      .filter((value) => {
        return value.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HAR;
      });
  }

  /**
   * 获取远程har依赖
   */
  getRemoteHarDependencies(): Dependency[] {
    return this.getHarDependencies().filter((dependency) => !dependency.isLocal());
  }

  /**
   * 获取所有hsp依赖
   * @returns {Dependency[]}
   */
  getHspDependencies(): Dependency[] {
    return this.getDependencyInfo()
      .getNpmDependencies()
      .filter((value) => {
        return value.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HSP;
      });
  }

  /**
   * 获取所有依赖类型map
   */
  getAllDependencyType(){
    const allDependencyTypeMap: Map<string, DependencyType> = new Map();
    const allDependencies = this.getAllDependencies();
    for(const dependency of allDependencies){
      allDependencyTypeMap.set(dependency.getDependencyName(), dependency.getDependencyType());
    }
    return allDependencyTypeMap;
  }

  /**
   * 获取字节码Har对应的Hsp map: Map<dependencyKey, hspPkgName[]>
   */
  getByteCodeHar2Hsp(): Map<string, string[]> {
    const ByteHarDependsOnHsp: Map<string, string[]> = new Map();
    const dependencyInfo = this.getDependencyInfo();
    const dependencies = dependencyInfo.getNpmDependencies();
    // 字节码har
    dependencies.forEach((value: Dependency) => {
      if (value.isByteCodeHarDependency()) {
        const dependencyKey = value.getDependencyName();
        ByteHarDependsOnHsp.set(dependencyKey, this.getHspRecursion(dependencyKey, dependencies));
      }
    });
    return ByteHarDependsOnHsp;
  }

  /**
   * 递归获取依赖树中的所有hsp
   */
  getHspRecursion(deptName: string, allDep: Dependency[], tempMap: Map<string, string[]> = new Map()): string[] {
    // 防止多次查询
    if (tempMap.has(deptName)) {
      return tempMap.get(deptName) || [];
    }
    const hspNameArr: string[] = [];
    tempMap.set(deptName, hspNameArr);

    const dept = allDep.find((dep) => dep.getDependencyName() === deptName);
    if (!dept?.getDependencies()) {
      this.log.debug(`No dependency is found: ${ deptName }`);
      return [];
    }
    const childDepsNames = Object.keys(dept.getDependencies());
    childDepsNames.forEach(depName => {
      const childDep = allDep.find(dept => dept.getDependencyName() === depName);
      if (childDep?.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HSP) {
        hspNameArr.push(depName);
      } else {
        hspNameArr.push(...this.getHspRecursion(depName, allDep, tempMap));
      }
    });
    return hspNameArr;
  }

  getHspOrByteCodeHarDependencies(): Dependency[] {
    return this.getDependencyInfo()
      .getNpmDependencies()
      .filter((value) => {
        return value.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HSP || value.isByteCodeHarDependency();
      });
  }

  /**
   * 获取所有so依赖
   * @returns {Dependency[]}
   */
  getSODependencies(): Dependency[] {
    return this.getDependencyInfo()
      .getAllDependencies()
      .filter((value) => {
        return value.getDependencyType() === DependencyType.DEPENDENCY_TYPE_SO;
      });
  }

  /**
   * 获取所有ohpm npm依赖
   * @returns {Dependency[]}
   */
  getOtherDependencies(): Dependency[] {
    return this.getDependencyInfo()
      .getAllDependencies()
      .filter((value) => {
        return value.getDependencyType() === DependencyType.DEPENDENCY_TYPE_OTHER;
      });
  }

  /**
   * 获取所有其他依赖
   * @returns {Dependency[]}
   */
  getAllDependencies(): Dependency[] {
    return this.getDependencyInfo().getAllDependencies();
  }

  private excludeChildrenWhenInDevDependencies(pkgNode?: ModulePkgNode) {
    if (!pkgNode) {
      return [];
    }
    return pkgNode.children
      // 保持原有规格，不收集devDependencies
      .filter(node => node.npm.getDependencyEnum() !== DependencyEnum.DEV_DEPENDENCIES);
  }

  getDirectPkgNodes() {
    const dependencyInfo = this.getDependencyInfo();
    const modulePkgNode = dependencyInfo.getModulePkgNode();
    const moduleChildren = this.excludeChildrenWhenInDevDependencies(dependencyInfo.getModulePkgNode());
    let projectChildren = this.excludeChildrenWhenInDevDependencies(dependencyInfo.getProjectPkgNode());
    if (!projectChildren.length) {
      return moduleChildren;
    }
    const isHap = modulePkgNode.npm.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HAP;
    // 保持规格，只有hap才会收集项目级的本地依赖
    if (!isHap) {
      projectChildren = projectChildren.filter(node => !node.npm.isLocal());
    }
    const moduleDependencyKeys = new Set(moduleChildren.map(node => node.npm.getDependencyName()));
    // 对于同名的依赖，模块级具有更高的优先级
    projectChildren = projectChildren
      .filter(node => !moduleDependencyKeys.has(node.npm.getDependencyName()));
    return moduleChildren.concat(projectChildren);
  }

  /**
   * 获取当前模块的直接依赖
   * @returns {Dependency[]}
   */
  getDirectDependencies(): Dependency[] {
    return this.getDirectPkgNodes().map(node => node.npm);
  }

  /**
   * 获取所有直接依赖子节点，包括devDependencies
   */
  getAllDirectPkgNodes(): ModulePkgNode[] {
    return this.getDependencyInfo().getDirectPkgNodes();
  }

  /**
   * 获取所有直接依赖，包括devDependencies，工程级本地依赖
   */
  getAllDirectDependencies(): Dependency[] {
    return this.getAllDirectPkgNodes().map(node => node.npm);
  }

  /**
   * 组建依赖树进行遍历收集，复用逻辑，调用_dependencyManager.collectFromTree
   * @param shouldTerminate 是否需要终止遍历，类型虽与_dependencyManager.collectFromTree一致，但返回值却被取反
   * @param shouldCollect 是否需要收集进最终的返回结果
   * @private
   */
  private collectFromTree(shouldTerminate: DependencyFilter, shouldCollect: DependencyCollector) {
    const modulePkgNode = this.getDependencyInfo().getModulePkgNode();
    const modulePath = modulePkgNode.npm.getDependencyRootPath();
    const root = { ...modulePkgNode, children: this.getAllDirectPkgNodes() };
    const npmDependencies: Dependency[] = [];
    const moduleDepMap: Map<string, Dependency> = new Map();
    const filter: DependencyFilter = (node, pre, post) => {
      const dependency = node.npm;
      // 自身的需要排除掉
      if (dependency.getDependencyRootPath() === modulePath) {
        this.log.debug(`Exclude current module dependency: ${dependency.getPackageName()}`);
        return false;
      }
      return !shouldTerminate(node, pre, post);
    };
    // 复用原有的收集逻辑
    this._dependencyManager.collectDependenciesFromTree({ root, npmDeps: npmDependencies, moduleDepMap, filter, shouldCollect });
    return { npmDependencies, moduleDepMap };
  }

  /**
   * 获取依赖链上的所有HSP，包括devDependencies，工程级本地HSP
   */
  @Cacheable(DependencyCacheKey.AllHspDependencies)
  getAllHspDependencies(): Dependency[] {
    // 三方库不会存在HSP
    const shouldTerminate: DependencyFilter = node => node.npm.isOtherDependency();
    const shouldCollect: DependencyCollector = node => node.npm.isHspDependency();
    return this.collectFromTree(shouldTerminate, shouldCollect).npmDependencies;
  }

  /**
   * 收集首层字节码HAR依赖，包括配置于devDependencies，工程级本地依赖的间接字节码HAR依赖
   * 只收集直接依赖中的字节码HAR，和被源码HAR依赖的字节码HAR
   * 1.HSP -> bytecodeHar，bytecodeHar不收集
   * 2.byteCodeHar -> dayjs，dayjs不收集
   * 3.byteCodeHar1 -> byteCodeHar2，byteCodeHar2不收集
   * 4.globalLocalHarDependency -> byteCodeHar，byteCodeHar收集
   */
  @Cacheable(DependencyCacheKey.RootByteCodeHarDependencies)
  getRootByteCodeHarDependencies(): Dependency[] {
    return this.getAffectsCompilationDependencies().filter(dependency => dependency.isByteCodeHarDependency());
  }

  /**
   * 收集首层NPM三方包依赖，包括配置于devDependencies，工程级本地依赖的间接NPM三方包依赖
   * 只收集直接依赖中的NPM三方包，和被源码HAR依赖的NPM三方包
   * 1.HSP -> dayjs，dayjs不收集，被hsp依赖的，不收集
   * 2.byteCodeHar -> dayjs，dayjs不收集，被字节码HAR依赖的不收集
   * 3.dayjs -> otherNpmPackage，otherNpmPackage不收集
   * 4.globalLocalHarDependency -> dayjs，dayjs收集
   */
  @Cacheable(DependencyCacheKey.RootOtherDependencies)
  getRootOtherDependencies(): Dependency[] {
    return this.getAffectsCompilationDependencies().filter(dependency => dependency.isOtherDependency());
  }

  /**
   * 收集首层HSP依赖，包括配置于devDependencies，工程级本地依赖
   * 1.HSP1 -> HSP2，HSP2不收集
   */
  @Cacheable(DependencyCacheKey.RootHspDependencies)
  getRootHspDependencies(): Dependency[] {
    const shouldTerminate: DependencyFilter = (node, _pre, post) => {
      const dependency = node.npm;
      if (dependency.isOtherDependency()) {
        return true;
      }
      return post && dependency.isHspDependency();
    };
    const shouldCollect: DependencyCollector = node => node.npm.isHspDependency();
    return this.collectFromTree(shouldTerminate, shouldCollect).npmDependencies;
  }

  /**
   * 在目前的编译逻辑中，在编译期间rollup有可能需要对以下依赖进行编译阻断：
   * 1.NPM三方包（bundled字节码HAR）
   * 2.HSP（所有模块）
   * 3.字节码HAR（所有模块）
   * 所以，当前这个函数，收集依赖逻辑如下（依赖包括配置于devDependencies，工程级本地依赖）：
   * 1.bytecodeHar -> any，bytecodeHar收集，依赖any不收集
   * 2.sourcecodeHar1 -> sourcecodeHar2 -> dayjs -> any，sourcecodeHar1，sourcecodeHar2，dayjs收集，依赖any不收集
   * 3.HSP -> any，HSP收集，依赖any不收集
   * 4.sourcecodeHar1 -> sourcecodeHar2 -> bytecodeHar -> any，sourcecodeHar1，sourcecodeHar2，bytecodeHar收集，依赖any不收集
   * 简单点理解，就是，当某个依赖可能需要被编译阻断时，只收集自身，其依赖（直接/间接）都不收集。
   */
  @Cacheable(DependencyCacheKey.AffectsCompilationDependencies)
  getAffectsCompilationDependencies() {
    const shouldTerminate: DependencyFilter = (node, _pre, post) => {
      return post && (node.npm.isHspDependency() || node.npm.isByteCodeHarDependency() || node.npm.isOtherDependency());
    };
    const shouldCollect: DependencyCollector = () => true;
    return this.collectFromTree(shouldTerminate, shouldCollect).npmDependencies;
  }

  /**
   * 收集所有字节码HAR依赖，包括配置于devDependencies，工程级本地依赖
   */
  @Cacheable(DependencyCacheKey.AllByteCodeHarDependencies)
  getAllByteCodeHarDependencies() {
    // 三方库不会存在字节码HAR
    const shouldTerminate: DependencyFilter = node => node.npm.isOtherDependency() || node.npm.isHspDependency();
    const shouldCollect: DependencyCollector = node => node.npm.isByteCodeHarDependency();
    return this.collectFromTree(shouldTerminate, shouldCollect).npmDependencies;
  }

  /**
   * 获取所有hsp依赖的路径的集合
   * @returns {Dependency[]}
   */
  getHspDependencyPaths(): string[] {
    return this.getHspDependencies()
      .filter((value) => value.getDependencyEnum() !== DependencyEnum.DYNAMIC_DEPENDENCIES)
      .map((value) => {
        return value.getDependencyRootPath();
      });
  }

  /**
   * 获取所有本地鸿蒙依赖模块
   * @returns {Dependency[]}
   */
  getModuleDependencies(): Dependency[] {
    return [...this.getDependencyInfo().getModuleDependencyMap().values()];
  }

  /**
   * 获取所有本地鸿蒙依赖模块的路径的集合
   * @returns {Dependency[]}
   */
  getModuleDependenciesPaths(): string[] {
    return this.getModuleDependencies().map((value) => {
      return value.getDependencyRootPath();
    });
  }

  /**
   * 获取所有本地依赖har模块
   * @returns {[string, Dependency][]}
   */
  getHarModuleDependencies(): [string, Dependency][] {
    return [...this.getDependencyInfo().getModuleDependencyMap().entries()].filter(([, value]) => {
      return value.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HAR;
    });
  }

  /**
   * 获取所有本地依赖har模块返回Map
   * @returns {Map<string, [string, Dependency]>}
   */
  getHarModuleDependenciesWithRootPath(): Map<string, [string, Dependency]> {
    const depMap = new Map();
    this.getDependencyInfo()
      .getModuleDependenciesByType(DependencyType.DEPENDENCY_TYPE_HAR)
      .forEach(([name, value]) => {
        depMap.set(value.getDependencyRootPath(), [name, value]);
      });
    return depMap;
  }

  /**
   * 获取所有本地依赖har模块的名称
   * @returns {string[]}
   */
  getHarModuleDependencyNames(): string[] {
    return this.getHarModuleDependencies().map(([key]) => {
      return key;
    });
  }

  /**
   * 获取所有本地依赖har模块的路径
   * @returns {string[]}
   */
  getHarModuleDependencyPaths(): string[] {
    return this.getHarModuleDependencies().map(([, value]) => {
      return value.getDependencyRootPath();
    });
  }

  /**
   * 获取所有本地依赖hsp模块
   * @returns {[string, Dependency][]}
   */
  getHspModuleDependencies(): [string, Dependency][] {
    return [...this.getDependencyInfo().getModuleDependencyMap().entries()].filter(([, value]) => {
      return value.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HSP;
    });
  }

  /**
   * 获取所有本地hsp依赖模块的名称
   * @returns {string[]}
   */
  getHspModuleDependencyNames(): string[] {
    return this.getHspModuleDependencies().map(([key]) => {
      return key;
    });
  }

  /**
   * 获取所有本地hsp依赖模块的路径
   * @returns {string[]}
   */
  getHspModuleDependencyPaths(): string[] {
    return this.getHspModuleDependencies().map(([, value]) => {
      return value.getDependencyRootPath();
    });
  }

  /**
   * 获取除Dynamic所有本地hsp依赖模块的路径
   * @returns {string[]}
   */
  getHspModuleDependencyPathsWithOutDynamic(): string[] {
    return this.getHspModuleDependencies()
      .filter(([, value]) => value.getDependencyEnum() !== DependencyEnum.DYNAMIC_DEPENDENCIES)
      .map(([, value]) => {
        return value.getDependencyRootPath();
      });
  }

  /**
   * 判断本模块是否有hsp依赖
   * @returns {[string, Dependency][]}
   */
  hasHspDependencies(): boolean {
    return this.getDependencyInfo().hasHspDependency();
  }

  getDependencyInfo(): ModuleDependencyInfo {
    !this._moduleDependencyInfo && this.initDependencyInfo();
    return this._moduleDependencyInfo as ModuleDependencyInfo;
  }

  getOhpmDependencyInfo() {
    const ohpmDependencyInfo: Record<string, OhpmDependencyInfo> = {};
    this.getDependencyInfo()
      .getNpmDependencies()
      .forEach((value: Dependency) => {
        ohpmDependencyInfo[value.getDependencyName()] = {
          name: value.getPackageName(),
          version: value.getDependencyVersion(),
          dependencies: value.getDependencies(),
          packagePath: value.getDependencyRootPath(),
        } as OhpmDependencyInfo;
      });
    return ohpmDependencyInfo;
  }

  getOhpmRemoteHspAllInfo(
    service: ModuleTaskService | ProjectTaskService,
    currentProduct: string | undefined,
    isSigned: boolean,
  ): Record<string, DependRemoteHspInfo> {
    const ohpmDependencyInfo: Record<string, DependRemoteHspInfo> = {};
    const npmDependencies: Dependency[] = this._dependencyManager.collectAllDependencies().npmDependencies;
    const remoteHspFileNameMap = getRemoteHspPathMap(service, npmDependencies);
    npmDependencies.forEach((value: Dependency) => {
      this.setDependencyInfo(value, remoteHspFileNameMap, isSigned, currentProduct, ohpmDependencyInfo);
    });
    return ohpmDependencyInfo;
  }

  private setDependencyInfo(value: Dependency,
    remoteHspFileNameMap: Map<string, string>,
    isSigned: boolean,
    currentProduct: string | undefined,
    ohpmDependencyInfo: Record<string, DependRemoteHspInfo>) {
    // 如果不满足条件则不进行收集
    if (!(!value.isLocal() && value.getDependencyType() === DependencyType.DEPENDENCY_TYPE_HSP)) {
      return;
    }
    const remoteHspDirName = this.getRemoteHspDirName(value.getDependencyRootPath());
    const remoteHspFileName = remoteHspFileNameMap.get(value.getPackageName());

    // 如果找不到目录名、或者oh_modules中.hsp目录下没有相应的hsp包则不收集
    if (!remoteHspDirName || !remoteHspFileName) {
      this.log.debug(`${value.getDependencyRootPath()} does not exist oh_modules.`);
      return;
    }
    let remoteHspPath;
    const pkgJsonObj = value.getPackageJsonObj() as any;
    const soPath = path.resolve(value.getDependencyRootPath(), 'libs');
    if (isSigned) {
      const signedRemoteHspPath = path.resolve(
        this._projectModel.getCacheRemoteHspPath(currentProduct ?? 'default'), remoteHspDirName, remoteHspFileName
          ? remoteHspFileName.replace(BuildArtifactExtension.DOT_HSP, `-signed${BuildArtifactExtension.DOT_HSP}`) : `${value.getPackageName()}-signed.hsp`,
      );
      ohpmDependencyInfo[value.getDependencyName()] = {
        name: value.getPackageName(),
        version: value.getDependencyVersion(),
        dependencies: value.getDependencies(),
        packagePath: value.getDependencyRootPath(),
        signedRemoteHspPath,
        soPath,
      } as DependRemoteHspInfo;
    } else {
      if (pkgJsonObj?.metadata?.integratedHsp) {
        remoteHspPath = path.resolve(
          this._projectModel.getCacheIntegratedHspPath(currentProduct ?? 'default'), remoteHspDirName, remoteHspFileName
            ? remoteHspFileName : `${value.getPackageName()}.hsp`,
        );
      } else {
        remoteHspPath = path.resolve(
          this.hvigorNode.getNodeDir(), 'oh_modules', '.hsp', remoteHspDirName, remoteHspFileName ? remoteHspFileName : `${value.getPackageName()}.hsp`,
        );
      }
      ohpmDependencyInfo[value.getDependencyName()] = {
        name: value.getPackageName(),
        version: value.getDependencyVersion(),
        dependencies: value.getDependencies(),
        packagePath: value.getDependencyRootPath(),
        remoteHspPath,
        soPath,
      } as DependRemoteHspInfo;
    }
  }

  /**
   *   获取dependencies中的远程hsp依赖,对外暴露的api
   *
   * @param service
   * @param currentProduct
   * @param isSigned
   */
  getOhpmRemoteHspDependencies(
    service: ModuleTaskService | ProjectTaskService,
    currentProduct: string | undefined,
    isSigned: boolean,
  ): Record<string, OhpmDependencyInfo> {
    const dependRemoteHspAllInfo: Record<string, DependRemoteHspInfo> = this.getOhpmRemoteHspAllInfo(service, currentProduct, isSigned);
    const dependRemoteHspInfo: Record<string, OhpmDependencyInfo> = {};
    Object.entries(dependRemoteHspAllInfo).forEach(([key, value]) => {
      if (isSigned) {
        dependRemoteHspInfo[key] = {
          name: value.name,
          version: value.version,
          dependencies: value.dependencies,
          packagePath: value.packagePath,
          signedRemoteHspPath: value.signedRemoteHspPath,
        };
      } else {
        dependRemoteHspInfo[key] = {
          name: value.name,
          version: value.version,
          dependencies: value.dependencies,
          packagePath: value.packagePath,
          remoteHspPath: value.remoteHspPath,
        };
      }
    });
    return dependRemoteHspInfo;
  }

  // 获取远程hsp的文件夹名
  getRemoteHspDirName(dependencyRootPath: string): string | undefined {
    const parts = toUnixPath(dependencyRootPath).split('/');
    const lastIndex = parts.lastIndexOf('oh_modules');
    if (lastIndex > 0) {
      return parts[lastIndex - 1];
    }
    return undefined;
  }

  /**
   * 获取依赖的arkTSVersion版本
   *
   * @param dependency
   */
  getDependencySelfArkTSVersion(dependency: Dependency): string {
    if (dependency.isLocal()) {
      const projectArkTSVersion = findTargetProduct(this._projectModel).arkTSVersion;
      const moduleArkTSVersion = this._projectModel.getModuleModelByName(dependency.getModuleName())?.getProfileOpt().arkTSVersion;
      return this.arkTSVersionArbitration(moduleArkTSVersion, projectArkTSVersion);
    } else {
      const packageJsonObj = dependency.getPackageJsonObj() as any;
      return packageJsonObj?.metadata?.arkTSVersion ?? ArkTSVersionConst.DEFAULT;
    }
  }

  /**
   * arkTSVersion版本仲裁，优先使用模块级别的配置
   * 模块级别未配置arkTSVersion时使用工程级别的配置
   *
   * @param moduleArkTSVersion 模块级arkTSVersion
   * @param projectArkTSVersion 工程级arkTSVersion
   */
  arkTSVersionArbitration(moduleArkTSVersion: string | undefined, projectArkTSVersion: string | undefined): string {
    if (moduleArkTSVersion) {
      return moduleArkTSVersion;
    }
    return projectArkTSVersion ? projectArkTSVersion : ArkTSVersionConst.DEFAULT;
  }
}
